package ie.dkit.semanticPhotoWeb.server.clientServerConnector;

import java.io.IOException;
import java.net.MalformedURLException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import ie.dkit.semanticPhotoWeb.client.ClientServerConnector;
import ie.dkit.semanticPhotoWeb.client.dtos.AlbumDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.CommentDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.InterestDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.PersonDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.RelationDTO;
import ie.dkit.semanticPhotoWeb.client.dtos.TagDTO;
import ie.dkit.semanticPhotoWeb.server.googleAPIHandler.PicasaAPIHandler;
import ie.dkit.semanticPhotoWeb.server.persistence.FOAFException;
import ie.dkit.semanticPhotoWeb.server.persistence.PersistenceHandler;
import ie.dkit.semanticPhotoWeb.server.persistence.PictureRelationException;
import ie.dkit.semanticPhotoWeb.server.persistence.storageObjects.Interest;
import ie.dkit.semanticPhotoWeb.server.persistence.storageObjects.Person;
import ie.dkit.semanticPhotoWeb.server.persistence.storageObjects.PictureRelation;
import ie.dkit.semanticPhotoWeb.server.semanticPhotoWebServer.SemanticPhotoWebCoreServer;

import com.google.gdata.client.http.AuthSubUtil;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.Link;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.TextContent;
import com.google.gdata.data.media.mediarss.MediaThumbnail;
import com.google.gdata.data.photos.AlbumEntry;
import com.google.gdata.data.photos.CommentEntry;
import com.google.gdata.data.photos.PhotoEntry;
import com.google.gdata.data.photos.TagEntry;
import com.google.gdata.data.photos.impl.ExifTag;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ParseException;
import com.google.gdata.util.ServiceException;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * @author Sebastian Ruehl
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
public class ClientServerConnectorImpl extends RemoteServiceServlet implements
		ClientServerConnector {

	private final static Logger logger = Logger
			.getLogger(ClientServerConnectorImpl.class.getName());

	/**
	 * 
	 */
	private static final long serialVersionUID = -1755202754316442179L;

	private String sessionToken, m_LoggedInUsername;

	private Integer userProfileID;

	private SemanticPhotoWebCoreServer serverCore;

	private PicasaAPIHandler m_GoogleAPIHandler;

	private PersistenceHandler m_PersistenceHandler;

	public ClientServerConnectorImpl() {
		serverCore = SemanticPhotoWebCoreServer.getInstance();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#addInterest(ie.dkit.semanticPhotoWeb.client.dtos.PersonDTO,
	 *      ie.dkit.semanticPhotoWeb.client.dtos.InterestDTO)
	 */
	public void addInterest(InterestDTO interestDTO) {
		try {
			getPersistenceHandler()
					.addInterest(getUserProfileID(), interestDTO);
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#addKnowRelation(ie.dkit.semanticPhotoWeb.client.dtos.PersonDTO)
	 */
	public void addKnowRelation(PersonDTO person) {
		try {
			getPersistenceHandler().addKnowRelation(getUserProfileID(), person);
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#addComment(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO,
	 *      java.lang.String)
	 */
	public void addComment(ImageDTO imageDTO, CommentDTO commentDTO) {
		try {
			CommentEntry entry = new CommentEntry();
			entry.setPublished(DateTime.now());
			entry.setContent(new PlainTextConstruct(commentDTO.commentContent));
			getPicasaAPIHandler().insert(imageDTO2PhotoEntry(imageDTO), entry);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#addTag(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO,
	 *      ie.dkit.semanticPhotoWeb.client.dtos.TagDTO)
	 */

	public void addTag(ImageDTO imageDTO, TagDTO tagDTO) {
		try {
			TagEntry entry = new TagEntry();
			entry.setTitle(new PlainTextConstruct(tagDTO.tagString));
			getPicasaAPIHandler().insert(imageDTO2PhotoEntry(imageDTO), entry);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteAlbum(ie.dkit.semanticPhotoWeb.client.dtos.AlbumDTO)
	 */
	public void deleteAlbum(AlbumDTO albumDTO) {
		try {
			albumDTO2AlbumEntry(albumDTO).delete();
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteComment(ie.dkit.semanticPhotoWeb.client.dtos.CommentDTO)
	 */
	public void deleteComment(CommentDTO commentDTO) {
		try {
			getPicasaAPIHandler().delete(commentDTO.editHref);
		} catch (MalformedURLException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteKnownRelation(ie.dkit.semanticPhotoWeb.client.dtos.PersonDTO)
	 */
	public void deleteKnownRelation(PersonDTO personDTO) {
		try {
			getPersistenceHandler().deleteKnowRelation(getUserProfileID(),
					personDTO.personID);
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteImage(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public void deleteImage(ImageDTO imageDTO) {
		try {
			imageDTO2PhotoEntry(imageDTO).delete();
			getPersistenceHandler().deleteAllRelationsByImageDTO(imageDTO);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteInterest(ie.dkit.semanticPhotoWeb.client.dtos.InterestDTO)
	 */
	public void deleteInterest(InterestDTO interestDTO) {
		try {
			getPersistenceHandler().deleteInterest(getUserProfileID(),
					interestDTO.id);
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteRelation(int)
	 */
	public void deleteRelation(RelationDTO relationDTO) {
		// You can only delete your own created relations
		try {
			if (getPersistenceHandler().getPictureRelationByID(
					relationDTO.relationID).getUsername().equals(
					getPicasaAPIHandler().getUsername())) {
				getPersistenceHandler().deletePictureRelation(
						relationDTO.relationID);
			}
		} catch (MalformedURLException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (PictureRelationException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#deleteTag(ie.dkit.semanticPhotoWeb.client.dtos.TagDTO)
	 */
	public void deleteTag(TagDTO tagDTO) {
		try {
			getPicasaAPIHandler().delete(tagDTO.editHref);
		} catch (MalformedURLException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/**
	 * maybe find a better way to ensure that a token will be revoked
	 */
	public void finalize() {
		logout();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getAlbumByName(java.lang.String,
	 *      java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public AlbumDTO getAlbumByName(String username, String albumName) {
		for (AlbumDTO album : (List<AlbumDTO>) getAlbums(username)) {
			if (album.albumName.equals(albumName)) {
				return album;
			}
		}
		throw new InvocationException("Album not Found");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getAlbum(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public AlbumDTO getAlbum(ImageDTO dto) {
		try {
			return albumEntry2AlbumDTO(getPicasaAPIHandler()
					.getAlbumEntryByFeedHref(dto.albumFeedHref));
		} catch (MalformedURLException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getAlbum()
	 */
	public List getAlbums() {
		return getAlbums(null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getAlbum(java.lang.String)
	 */
	public List getAlbums(String username) {
		List<AlbumDTO> returnAlbumDTOs = new ArrayList<AlbumDTO>();
		try {
			List<AlbumEntry> list;
			if (username == null) {
				list = getPicasaAPIHandler().getAlbums();
			} else {
				list = getPicasaAPIHandler().getAlbums(username);
			}
			for (AlbumEntry entry : list) {
				returnAlbumDTOs.add(albumEntry2AlbumDTO(entry));
			}
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
		return returnAlbumDTOs;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getAuthLink()
	 */
	public String getAuthLink() {
		return Login.getAuthURL();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getComments(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public List getComments(ImageDTO imageDTO) {
		String editHref;
		Link editLink;
		try {
			PhotoEntry photoEntry = imageDTO2PhotoEntry(imageDTO);
			List<CommentEntry> entrys = getPicasaAPIHandler().getComments(
					photoEntry);

			List<CommentDTO> returnComments = new ArrayList<CommentDTO>();
			for (CommentEntry entry : entrys) {
				editLink = entry.getEditLink();
				boolean editable = (editLink != null);
				editHref = editable ? entry.getEditLink().getHref() : entry
						.getSelfLink().getHref();
				returnComments.add(new CommentDTO(editHref, entry.getTitle()
						.getPlainText(), entry.getPublished().toString(),
						((TextContent) entry.getContent()).getContent()
								.getPlainText(), editable));
			}
			return returnComments;
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getImageByID(java.lang.String,
	 *      java.lang.String, java.lang.String)
	 */
	@SuppressWarnings("unchecked")
	public ImageDTO getImageByID(String username, String albumName,
			String imageID) {
		for (ImageDTO image : (List<ImageDTO>) getImages(getAlbumByName(
				username, albumName))) {
			if (image.imageID.substring(image.imageID.lastIndexOf('/') + 1)
					.equals(imageID.replaceAll("photo#", ""))) {
				return image;
			}
		}
		throw new InvocationException("Image not found");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getImages(java.lang.String)
	 */
	public List getImages(AlbumDTO albumDTO) {
		List<ImageDTO> returnImages = new ArrayList<ImageDTO>();
		try {
			// found
			for (PhotoEntry photo : getPicasaAPIHandler().getPhotos(
					albumDTO2AlbumEntry(albumDTO))) {
				ImageDTO imageDTO = photoEntry2ImageDTO(photo);
				imageDTO.albumName = albumDTO.albumName;
				imageDTO.albumFeedHref = albumDTO.feedRef;
				returnImages.add(imageDTO);
			}
			return returnImages;
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (NullPointerException e) {
			logger.info("User tried to access unknown Album:"
					+ albumDTO.albumName);
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getLinkedPictures(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public List getLinkedPictures(ImageDTO dto) {
		ArrayList<RelationDTO> relations = new ArrayList<RelationDTO>();
		for (PictureRelation relation : getPersistenceHandler()
				.getLinkedPictures(dto)) {
			try {
				relations
						.add(new RelationDTO(
								photoEntry2ImageDTO(getPicasaAPIHandler()
										.getPhotoEntryByID(
												relation.getSecondPhotoID())),
								relation.getId(), relation.getRelationTyp()));
			} catch (IOException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			} catch (ServiceException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			}
		}
		return relations;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getReferringPictures(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public List getReferringPictures(ImageDTO dto) {
		ArrayList<RelationDTO> relations = new ArrayList<RelationDTO>();
		for (PictureRelation relation : getPersistenceHandler()
				.getReferringPictures(dto)) {
			try {
				relations
						.add(new RelationDTO(
								photoEntry2ImageDTO(getPicasaAPIHandler()
										.getPhotoEntryByID(
												relation.getFirstPhotoID())),
								relation.getId(), relation.getRelationTyp()));
			} catch (IOException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			} catch (ServiceException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			}
		}
		return relations;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getTags(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO)
	 */
	public List getTags(ImageDTO imageDTO) {
		try {
			PhotoEntry photoEntry = imageDTO2PhotoEntry(imageDTO);
			List<TagEntry> entrys = getPicasaAPIHandler().getTags(photoEntry);
			return tagEntryList2tagDTOList(entrys);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getTags(ie.dkit.semanticPhotoWeb.client.dtos.AlbumDTO)
	 */
	public List getTags(AlbumDTO albumDTO) {
		try {
			List<TagEntry> entrys = getPicasaAPIHandler().getTags(
					albumDTO2AlbumEntry(albumDTO));
			return tagEntryList2tagDTOList(entrys);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getUserProfile()
	 */
	public PersonDTO getUserProfile() {
		try {
			return person2PersonDTO(getPersistenceHandler().getPersonByID(
					getUserProfileID()));
		} catch (FOAFException e) {
			throw new InvocationException(
					"Error on Server. Please contact admin" + e.getMessage());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getUserProfileByUserName(java.lang.String)
	 */
	public PersonDTO getUserProfileByUserName(String username) {
		try {
			return person2PersonDTO(getPersistenceHandler()
					.getPersonByUsername(username));
		} catch (FOAFException e) {
			return person2PersonDTO(getPersistenceHandler()
					.createNewUserProfile(username));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getUserName()
	 */
	public String getUserName() {
		try {
			return getPicasaAPIHandler().getUsername();
		} catch (MalformedURLException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getUserTags()
	 */
	public List getUserTags() {
		return getUserTags(null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getUserTags(java.lang.String)
	 */
	public List getUserTags(String username) {
		try {
			List<TagEntry> entrys;
			if (username == null) {
				entrys = getPicasaAPIHandler().getTags();
			} else {
				entrys = getPicasaAPIHandler().getTags(username);
			}
			List<TagDTO> returnTags = new ArrayList<TagDTO>();
			for (TagEntry entry : entrys) {
				Integer weigth = entry.getWeight();
				if (weigth == null) {
					weigth = Integer.valueOf(-1);
				}
				returnTags.add(new TagDTO(entry.getTitle().getPlainText(),
						entry.getSelfLink().getHref(), weigth, false));
			}
			return returnTags;
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#getRDFFileByPersonID(int)
	 */
	public String getRDFFileByPersonID(int id) {
		try {
			FOAF foaf = new FOAF();
			Person person = getPersistenceHandler().getPersonByID(id);
			foaf.consumePerson(person);
			return foaf.toString();
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException("Profile not available");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#isLoggedIn()
	 */
	public boolean isLoggedIn() {
		return sessionToken != null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#linkToOtherPicture(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO,
	 *      ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO, java.lang.String)
	 */
	public void linkToOtherPicture(ImageDTO dto1, ImageDTO dto2, String typ) {
		getPersistenceHandler().linkToOtherPicture(m_LoggedInUsername, dto1,
				dto2, typ);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#login(java.lang.String)
	 */
	public String login(String authSubToken) {
		logger.info("client login with followein authSubToken:" + authSubToken);
		try {
			sessionToken = AuthSubUtil.exchangeForSessionToken(authSubToken,
					null);
			getPicasaAPIHandler().setAuthSubToken(sessionToken);
			m_LoggedInUsername = getPicasaAPIHandler().getUsername();
			return m_LoggedInUsername;
		} catch (AuthenticationException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (GeneralSecurityException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#logout()
	 */
	public void logout() {
		if (sessionToken != null) {
			try {
				AuthSubUtil.revokeToken(sessionToken, null);
				sessionToken = null;
				m_LoggedInUsername = null;
			} catch (AuthenticationException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			} catch (IOException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			} catch (GeneralSecurityException e) {
				logger.warning(e.getMessage());
				e.printStackTrace();
				throw new InvocationException(e.getClass().getName()
						+ ". Please Check Server log");
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#updateUserProfile(ie.dkit.semanticPhotoWeb.client.dtos.PersonDTO)
	 */
	public void updateUserProfile(PersonDTO personDTO) {
		try {
			getPersistenceHandler()
					.updateProfile(getUserProfileID(), personDTO);
		} catch (FOAFException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#updateSummary(ie.dkit.semanticPhotoWeb.client.dtos.ImageDTO,
	 *      java.lang.String)
	 */
	public void updateSummary(ImageDTO imageDTO, String summary) {
		try {
			PhotoEntry entry = imageDTO2PhotoEntry(imageDTO);
			entry.setSummary(new PlainTextConstruct(summary));
			entry.update();
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see ie.dkit.semanticPhotoWeb.client.ClientServerConnector#newAlbum(java.lang.String,
	 *      java.lang.String, java.lang.String, java.lang.String,
	 *      java.lang.String)
	 */
	public boolean newAlbum(String albumTitle, String description) {
		AlbumEntry albumEntry = new AlbumEntry();

		albumEntry.setTitle(new PlainTextConstruct(albumTitle));
		albumEntry.setDescription(new PlainTextConstruct(description));

		try {
			getPicasaAPIHandler().insertAlbum(albumEntry);
			return true;
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	// /////////////////////////////////////////////////////
	// / <HelperMethods>
	// /////////////////////////////////////////////////////

	private AlbumEntry albumDTO2AlbumEntry(AlbumDTO dto) {
		try {
			for (AlbumEntry entry : getPicasaAPIHandler().getAlbums(
					dto.username)) {
				if (entry.getName().equals(dto.albumName)) {
					return entry;
				}
			}
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
		return null;
	}

	private AlbumDTO albumEntry2AlbumDTO(AlbumEntry entry) {
		try {
			String url = entry.getMediaThumbnails().get(0).getUrl();

			return new AlbumDTO(entry.getSelfLink().getHref(), url, entry
					.getName(), entry.getUsername(), entry.getDate().toString());
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
			throw new InvocationException(e.getClass().getName()
					+ ". Please Check Server log");
		}
	}

	private int getUserProfileID() {
		if (userProfileID == null) {
			if (!isLoggedIn()) {
				throw new InvocationException(
						"You must be logged in to call this service!");
			}
			Person person;
			try {
				person = getPersistenceHandler().getPersonByUsername(
						getUserName());
				userProfileID = person.getId();
			} catch (FOAFException e) {
				person = getPersistenceHandler().createNewUserProfile(
						getUserName());
				e.printStackTrace();
				logger.warning(e.getMessage()
						+ ": Creating new Profile with id: " + person.getId());
				userProfileID = person.getId();
			}
		}
		return userProfileID;
	}

	private PicasaAPIHandler getPicasaAPIHandler() {
		if (m_GoogleAPIHandler == null) {
			m_GoogleAPIHandler = serverCore.getPicasaAPIHandler();
		}
		return m_GoogleAPIHandler;
	}

	private PersistenceHandler getPersistenceHandler() {
		if (m_PersistenceHandler == null) {
			m_PersistenceHandler = serverCore.getPersistenceHandler();
		}
		return m_PersistenceHandler;
	}

	private PhotoEntry imageDTO2PhotoEntry(ImageDTO imageDTO) {
		try {
			return getPicasaAPIHandler().getPhotoEntryByID(imageDTO.imageID);
		} catch (IOException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
		} catch (ServiceException e) {
			logger.warning(e.getMessage());
			e.printStackTrace();
		}
		return null;
	}

	private PersonDTO person2PersonDTO(Person person) {
		List<InterestDTO> interests = new ArrayList<InterestDTO>();
		for (Interest i : person.getInterests()) {
			interests.add(new InterestDTO(i.getInterestID(), i.getAbout(), i
					.getTitle()));
		}
		List<PersonDTO> knows = new ArrayList<PersonDTO>();
		for (Person p : person.getKnows()) {
			PersonDTO personDTO = new PersonDTO();
			personDTO.personID = p.getId();
			personDTO.name = p.getName();
			personDTO.username = p.getUsername();
			knows.add(personDTO);
		}
		return new PersonDTO(person.getId(), ServerPropertiesParser
				.getString("Server.RDF_ADDR")
				+ "?profileID=" + person.getId(), person.getUsername(), person
				.getName(), person.getEmail(), person.getHomepage(), person
				.getNick(), person.getPhoto(), interests
				.toArray(new InterestDTO[0]), knows.toArray(new PersonDTO[0]));
	}

	private ImageDTO photoEntry2ImageDTO(PhotoEntry photoEntry) {
		StringBuilder exifTagsString = new StringBuilder();
		for (ExifTag exifTag : photoEntry.getExifTags().getExifTags()) {
			exifTagsString.append(exifTag.getName() + ':' + exifTag.getValue()
					+ '\n');
		}

		String[] thumbnails = new String[photoEntry.getMediaThumbnails().size()];
		int i = 0;
		for (MediaThumbnail thumbnail : photoEntry.getMediaThumbnails()) {
			thumbnails[i++] = thumbnail.getUrl();
		}

		Link editLink = photoEntry.getEditLink();
		boolean editable = (editLink != null);
		String editHref = editable ? photoEntry.getEditLink().getHref()
				: photoEntry.getSelfLink().getHref();

		String imageUrl = photoEntry.getMediaContents().get(0).getUrl();
		return new ImageDTO(thumbnails, imageUrl, photoEntry.getId(),
				photoEntry.getTitle().getPlainText(), photoEntry.getSummary()
						.getPlainText(), editHref, editable, exifTagsString
						.toString());
	}

	private List<TagDTO> tagEntryList2tagDTOList(List<TagEntry> entries) {
		String editHref;
		Link editLink;
		List<TagDTO> returnTags = new ArrayList<TagDTO>();
		for (TagEntry entry : entries) {
			Integer weigth;
			try {
				weigth = entry.getWeight();
				if (weigth == null) {
					weigth = Integer.valueOf(-1);
				}
			} catch (ParseException e) {
				// Should be never thrown
				weigth = Integer.valueOf(-1);
			}
			editLink = entry.getEditLink();
			boolean editable = (editLink != null);
			editHref = editable ? entry.getEditLink().getHref() : entry
					.getSelfLink().getHref();
			returnTags.add(new TagDTO(entry.getTitle().getPlainText(),
					editHref, weigth, editable));
		}
		return returnTags;
	}

	// /////////////////////////////////////////////////////
	// / </HelperMethods>
	// /////////////////////////////////////////////////////

}
